namespace Resonator.Tests.Services
{
	using System.Collections.Generic;
	using System.Globalization;
	using NHibernate.Expressions;
	using NUnit.Framework;
	using Resonator.Core.Services;
	using Resonator.Domain.Models;
	using Resonator.Domain.Services;
	using Rhino.Mocks;

	[TestFixture]
	[Category("Resolver")]
	public class ResourceResolverTester
	{
		#region Setup/Teardown

		[SetUp]
		public void SetUp()
		{
			_mocks = new MockRepository();
			_dbResources = new List<Resource>();
			_ftResources = new List<Resource>();
			_resourcesToResolve = new List<Resource>();

			_resourceRepository = _mocks.DynamicMock<IRepository<Resource>>();
			SetupResult.For( _resourceRepository.CreateSessionScope() ).Return( new MockSessionScope() );  
			_resolver = new ResourceResolver( _resourceRepository );
		}

		#endregion

		private MockRepository _mocks;
		private IResourceResolver _resolver;
		private IRepository<Resource> _resourceRepository;
		private List<Resource> _dbResources;
		private List<Resource> _ftResources;
		private List<Resource> _resourcesToResolve;

		[Test]
		public void Empty_Resources_Or_Required_Cultures_Returns_Empty_Result()
		{
			IList<ResolveResult> results = _resolver.Resolve( null, new CultureInfo[0] );

			Assert.IsNotNull( results );
			Assert.AreEqual( 0, results.Count );

			results = _resolver.Resolve( new Resource[0], null );

			Assert.IsNotNull( results );
			Assert.AreEqual( 0, results.Count );
		}

		[Test]
		public void If_No_Matches_In_Db_Or_Ft_Then_Return_Was_Not_Found()
		{
			_resourcesToResolve.Add( Resource.Create( "Yes" ) );

			SetupResult.For(_resourceRepository.FindAll((DetachedCriteria)null)).IgnoreArguments().Return(_dbResources.ToArray());
			SetupResult.For( _resourceRepository.Search( "Yes" ) ).Return( _ftResources.ToArray() );

			_mocks.ReplayAll();

			IList<ResolveResult> results = _resolver.Resolve( _resourcesToResolve, new CultureInfo[] {new CultureInfo( "es-ES" )} );

			_mocks.VerifyAll();

			Assert.AreEqual( 1, results.Count );
			Assert.IsTrue( results[0].WasNotFound );
		}

		[Test]
		public void If_Phrase_Does_Not_Match_Resource_In_Db_Then_Ft_Is_Searched_And_Returned_As_Partial_Match()
		{
			_ftResources.Add( Resource.Create( "Yes" ).AddTranslation( "it-IT", "Si" ) );
			_resourcesToResolve.Add( Resource.Create( "Yes" ) );

			SetupResult.For(_resourceRepository.FindAll((DetachedCriteria)null)).IgnoreArguments().Return(_dbResources.ToArray());
			SetupResult.For( _resourceRepository.Search( "Yes" ) ).Return( _ftResources.ToArray() );

			_mocks.ReplayAll();

			IList<ResolveResult> results = _resolver.Resolve( _resourcesToResolve, new CultureInfo[] {new CultureInfo( "es-ES" )} );

			_mocks.VerifyAll();

			Assert.AreEqual( 1, results.Count );
			Assert.IsTrue( results[0].HasPartialMatches );
			Assert.AreEqual( _ftResources[0], results[0].PartialMatches[0].Resource );
			Assert.IsFalse( results[0].PartialMatches[0].HasAllCulturesRequested );
		}

		[Test]
		public void If_Phrase_Matches_Resource_In_Db_Then_Exact_Match_Is_Returned()
		{
			_dbResources.Add( Resource.Create( "Yes" ).AddTranslation( "es-ES", "Si" ) );
			_resourcesToResolve.Add( Resource.Create( "Yes" ) );

			SetupResult.For( _resourceRepository.FindAll( (DetachedCriteria)null) ).IgnoreArguments().Return( _dbResources.ToArray() );

			_mocks.ReplayAll();

			IList<ResolveResult> results = _resolver.Resolve( _resourcesToResolve, new CultureInfo[] {new CultureInfo( "es-ES" )} );

			_mocks.VerifyAll();

			Assert.AreEqual( 1, results.Count );
			Assert.IsTrue( results[0].HasExactMatch );
			Assert.AreEqual( _dbResources[0], results[0].ExactMatch.Resource );
			Assert.IsTrue( results[0].ExactMatch.HasAllCulturesRequested );
		}
	}
}